package pl.ivmx.cinema;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

import pl.ivmx.cinema.entities.Logmovie;
import pl.ivmx.cinema.entities.Movie;

public class MovieDao extends BaseDao {

	public static String WHICH_METHOD = "JPA"; // "JDBC" OR "JPA"
	private static MovieDao instance = null;
	private List<MovieObserver> observers;

	
	private List<BasicEntity> notifications;
	private ThreadManager threadManager;
	private DaoThread daoThread;
	private EntityManager em;
	
	private MovieDao() {
		
		threadManager = ThreadManager.getInstance();
		notifications = new ArrayList<BasicEntity>();
		observers = new ArrayList<MovieObserver>();
		EntityManagerFactory emf = 
			Persistence.createEntityManagerFactory("cinemaJPA");
		em = emf.createEntityManager();
	}

	public List<Movie> getAllMovies(){
		Query q = em.createNamedQuery("movies.AllMovies");
		em.getTransaction().begin();
		List<Movie> lista = q.getResultList();
		
		em.getTransaction().commit();
		
		return lista;
	}
	
	public static MovieDao getInstance() {
		if (instance == null) {
			instance = new MovieDao();
		}
		return instance;
	}
	
	private void findNotificationJPA(){
		em.getTransaction().begin();
		Query q = em.createNamedQuery("logmovie.getLogmovies");
	    List<Logmovie> listaLogow = q.getResultList();
	    
	    for (Logmovie logmovie : listaLogow) {
			long logID = logmovie.getId();
			int newMovie = logmovie.getMovieId().intValue();
			System.out.println("(JPA) Nowy log film : "+newMovie);
			
			Query qMovies = em.createNamedQuery("movie.findMoviesWithId");
			
			qMovies.setParameter("id", newMovie );
			Movie m = (Movie) qMovies.getSingleResult();
			notifications.add(m);
			
			em.remove(logmovie);
		}
	    
	    em.getTransaction().commit();
	}
	
	private void finNotificationJDBC(){
		ResultSet newMovies = JDBCConnection.getInstance().executeQuery(
		"Select * from LogMovie");
		String movieID;
		try {
				while (newMovies.next()) {
		String logID = newMovies.getString("id");
		
		movieID = newMovies.getString("movie_id");

		ResultSet movies = JDBCConnection.getInstance().executeQuery(
				"Select * from movie where id=" + movieID);

		try {
			while (movies.next()) {

				String director = movies.getString("director");
				Integer id = Integer.parseInt(movies.getString("id"));
				String releaseDate = movies.getString("release_date");
				String title = movies.getString("title");

				MovieEntity movie = new MovieEntity(id, title,
						director, releaseDate);

				notifications.add(movie);

			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		JDBCConnection.getInstance().executeStatement("delete from LogMovie where id = " + logID);
	}
} catch (SQLException e1) {
	e1.printStackTrace();
}
	}
	
	@Override
	public void findNotifications() {
		if (MovieDao.WHICH_METHOD == "JDBC")
			finNotificationJDBC();
		else
			findNotificationJPA();
		
		
	}

	@Override
	public void addListener(IObserver io) {
		if (io instanceof MovieObserver) {
			observers.add((MovieObserver) io);
			
		}
		
		if (observers.size() == 1 ){
			if (daoThread == null) {
				daoThread = (DaoThread) ThreadManager.getInstance().createThread(this);
				
			}
			ThreadManager.getInstance().start(daoThread);
		} 
	}

	@Override
	public void notifyListener() {
		for(BasicEntity be : notifications){
			for(MovieObserver o : observers){
				o.update(be);
			}
		}
		notifications.clear();
	}

	@Override
	public void removeListener(IObserver io) {
		if (io instanceof MovieObserver) {
			observers.remove((MovieObserver) io);
		}
		
		if (observers.size() == 0){
			if (daoThread != null){
				ThreadManager.getInstance().stopThread(daoThread);
			}
		}
	}

}
